package com.hmall.search.service.impl;

import cn.hutool.core.util.ObjectUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.FunctionBoostMode;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.json.JsonData;
import com.hmall.common.domain.PageDTO;
import com.hmall.search.domain.po.ItemDoc;
import com.hmall.search.domain.query.ItemPageQuery;
import com.hmall.search.service.ISearchService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service
@Slf4j
@AllArgsConstructor
public class SearchServiceImpl implements ISearchService {

    private final ElasticsearchClient esClient;


    @Override
    public PageDTO<ItemDoc> search(ItemPageQuery query) throws IOException {
        //执行搜索
        SearchResponse<ItemDoc> response = esClient.search(builder -> builder.index("items")
                        .query(queryBuilder -> queryBuilder.functionScore(fsBuilder -> fsBuilder
                                .query(qb -> qb.bool(boolBuilder -> {
                                            //搜索key不为空
                                            if (ObjectUtil.isNotEmpty(query.getKey())) {
                                                boolBuilder.must(mustBuilder -> mustBuilder.match(mb -> mb.field("name").query(query.getKey())));
                                            }
                                            //判断分类不为空
                                            if (ObjectUtil.isNotEmpty(query.getCategory())) {
                                                boolBuilder.filter(fb -> fb.term(termBuilder -> termBuilder.field("category").value(query.getCategory())));
                                            }
                                            //如果品牌不为空
                                            if (ObjectUtil.isNotEmpty(query.getBrand())) {
                                                boolBuilder.filter(fb -> fb.term(termBuilder -> termBuilder.field("brand").value(query.getBrand())));
                                            }
                                            //如果价格不为空
                                            if (query.getMinPrice() != null) {
                                                boolBuilder.filter(fb -> fb.range(rangeBuilder -> rangeBuilder.field("price").gte(JsonData.of(query.getMinPrice()))));
                                            }
                                            if (query.getMaxPrice() != null) {
                                                boolBuilder.filter(fb -> fb.range(rangeBuilder -> rangeBuilder.field("price").lte(JsonData.of(query.getMaxPrice()))));
                                            }
                                            return boolBuilder;
                                        }
                                ))
                                .functions(fb -> fb
                                        .filter(f -> f.term(termBuilder -> termBuilder.field("isAD").value(true)))
                                        .weight(100D))
                                .boostMode(FunctionBoostMode.Multiply)))

                        .sort(sortBuilder -> {
                            //判断排序字段是否为空，为空则默认_score排序
                            if (ObjectUtil.isEmpty(query.getSortBy())) {
                                sortBuilder.field(f -> f.field("_score").order(query.getIsAsc() ? SortOrder.Asc : SortOrder.Desc));
                            } else {
                                //排序按销量，和价格
                                sortBuilder.field(f -> f.field(query.getSortBy()).order(query.getIsAsc() ? SortOrder.Asc : SortOrder.Desc));
                            }
                            return sortBuilder;
                        })
                        .from((query.getPageNo() - 1) * query.getPageSize())//(页码-1)*每页数量
                        .size(query.getPageSize())
                        .highlight(hlBuilder -> hlBuilder.fields("name", fieldBuilder -> fieldBuilder.preTags("<em style='color:red'>")
                                .postTags("</em>"))),
                ItemDoc.class);

        //封装结果
        //获取总数量
        long total = response.hits().total().value();
        //获取查询列表
        List<ItemDoc> list = new ArrayList<>();
        List<Hit<ItemDoc>> hits = response.hits().hits();
        for (Hit<ItemDoc> hit : hits) {
            //获取单个商品
            ItemDoc doc = hit.source();
            //获取高亮数据
            Map<String, List<String>> highlight = hit.highlight();
            if (ObjectUtil.isNotEmpty(highlight)) {
                List<String> name = highlight.get("name");
                if (ObjectUtil.isNotEmpty(name)) {
                    doc.setName(name.get(0));
                }
                list.add(doc);
            }
        }
        PageDTO<ItemDoc> pageDTO = new PageDTO<>();
        pageDTO.setTotal(total);
        pageDTO.setList(list);
        return pageDTO;
    }
}
